Grant tables for FreeBSD.
Signed-off-by: Kip Macy <kmacy@fsmware.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
423e7e88B5vxFblc-MlhxKk9e4ieBw freebsd-5.3-xen-sparse/i386-xen/i386-xen/evtchn.c
423e7e88z_BrFu1O71-Ya4pXJpjAPQ freebsd-5.3-xen-sparse/i386-xen/i386-xen/exception.s
423e7e88uDvAZLmABMkqOpmemyVRyw freebsd-5.3-xen-sparse/i386-xen/i386-xen/genassym.c
+4266317eeOLpvRxIjmOYQVlL4WWQsg freebsd-5.3-xen-sparse/i386-xen/i386-xen/gnttab.c
423e7e88yr5NFQudubMnkvdb_y-Gtg freebsd-5.3-xen-sparse/i386-xen/i386-xen/hypervisor.c
423e7e88Y-e-4RRf9nrgkVn5PXUv3Q freebsd-5.3-xen-sparse/i386-xen/i386-xen/i686_mem.c
423e7e88b8m2cuGtOxVvs4Sok4Vk7Q freebsd-5.3-xen-sparse/i386-xen/i386-xen/initcpu.c
423e7e8avrrUxDugrwq_GJp499DkJw freebsd-5.3-xen-sparse/i386-xen/include/ctrl_if.h
423e7e8apY1r9Td-S0eZITNZZbfNTQ freebsd-5.3-xen-sparse/i386-xen/include/evtchn.h
423e7e8aL9DsObEegCwtILrF6SWcAQ freebsd-5.3-xen-sparse/i386-xen/include/frame.h
+4266317eOVvN00XdcqRfDRFIrbqgvg freebsd-5.3-xen-sparse/i386-xen/include/gnttab.h
423e7e8btv8Gojq50ggnP5A1Dkc4kA freebsd-5.3-xen-sparse/i386-xen/include/hypervisor-ifs.h
423e7e8buhTLVFLZ33-5s8-UdADSZg freebsd-5.3-xen-sparse/i386-xen/include/hypervisor.h
423e7e8bnHT1kMD-FPC7zHZR7l3VXw freebsd-5.3-xen-sparse/i386-xen/include/md_var.h
i386-xen/i386-xen/pmap.c standard
i386-xen/i386-xen/support.s standard
i386-xen/i386-xen/swtch.s standard
-i386-xen/i386-xen/sys_machdep.c standard
+i386-xen/i386-xen/sys_machdep.c standard
i386-xen/i386-xen/trap.c standard
i386/i386/tsc.c standard
-i386-xen/i386-xen/vm_machdep.c standard
+i386-xen/i386-xen/vm_machdep.c standard
i386-xen/i386-xen/clock.c standard
# xen specific arch-dep files
i386-xen/i386-xen/hypervisor.c standard
i386-xen/i386-xen/xen_machdep.c standard
-i386-xen/i386-xen/xen_bus.c standard
-i386-xen/i386-xen/evtchn.c standard
-i386-xen/i386-xen/ctrl_if.c standard
+i386-xen/i386-xen/xen_bus.c standard
+i386-xen/i386-xen/evtchn.c standard
+i386-xen/i386-xen/ctrl_if.c standard
+i386-xen/i386-xen/gnttab.c standard
i386/isa/asc.c count asc
--- /dev/null
+/******************************************************************************
+ * gnttab.c
+ *
+ * Two sets of functionality:
+ * 1. Granting foreign access to our memory reservation.
+ * 2. Accessing others' memory reservations via grant references.
+ * (i.e., mechanisms for both sender and recipient of grant references)
+ *
+ * Copyright (c) 2005, Christopher Clark
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#include "opt_pmap.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/module.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+
+#include <machine/gnttab.h>
+#include <machine/pmap.h>
+
+#include <machine/hypervisor-ifs.h>
+
+#define cmpxchg(a, b, c) atomic_cmpset_int((volatile u_int *)(a),(b),(c))
+
+
+/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
+static inline void rep_nop(void)
+{
+ __asm__ __volatile__ ( "rep;nop" : : : "memory" );
+}
+#define cpu_relax() rep_nop()
+
+#if 1
+#define ASSERT(_p) \
+ if ( !(_p) ) { printk("Assertion '%s': line %d, file %s\n", \
+ #_p , __LINE__, __FILE__); *(int*)0=0; }
+#else
+#define ASSERT(_p) ((void)0)
+#endif
+
+#define WPRINTK(fmt, args...) \
+ printk("xen_grant: " fmt, ##args)
+
+static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES];
+static grant_ref_t gnttab_free_head;
+
+static grant_entry_t *shared;
+#if 0
+/* /proc/xen/grant */
+static struct proc_dir_entry *grant_pde;
+#endif
+
+/*
+ * Lock-free grant-entry allocator
+ */
+
+static inline int
+get_free_entry(void)
+{
+ grant_ref_t fh, nfh = gnttab_free_head;
+ do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; }
+ while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh,
+ gnttab_free_list[fh])) != fh) );
+ return fh;
+}
+
+static inline void
+put_free_entry(grant_ref_t ref)
+{
+ grant_ref_t fh, nfh = gnttab_free_head;
+ do { gnttab_free_list[ref] = fh = nfh; wmb(); }
+ while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
+}
+
+/*
+ * Public grant-issuing interface functions
+ */
+
+int
+gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
+{
+ int ref;
+
+ if ( unlikely((ref = get_free_entry()) == -1) )
+ return -ENOSPC;
+
+ shared[ref].frame = frame;
+ shared[ref].domid = domid;
+ wmb();
+ shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+
+ return ref;
+}
+
+void
+gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+ unsigned long frame, int readonly)
+{
+ shared[ref].frame = frame;
+ shared[ref].domid = domid;
+ wmb();
+ shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+}
+
+
+int
+gnttab_query_foreign_access(grant_ref_t ref)
+{
+ uint16_t nflags;
+
+ nflags = shared[ref].flags;
+
+ return (nflags & (GTF_reading|GTF_writing));
+}
+
+void
+gnttab_end_foreign_access(grant_ref_t ref, int readonly)
+{
+ uint16_t flags, nflags;
+
+ nflags = shared[ref].flags;
+ do {
+ if ( (flags = nflags) & (GTF_reading|GTF_writing) )
+ printk("WARNING: g.e. still in use!\n");
+ }
+ while ( (nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags );
+
+ put_free_entry(ref);
+}
+
+int
+gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
+{
+ int ref;
+
+ if ( unlikely((ref = get_free_entry()) == -1) )
+ return -ENOSPC;
+
+ shared[ref].frame = pfn;
+ shared[ref].domid = domid;
+ wmb();
+ shared[ref].flags = GTF_accept_transfer;
+
+ return ref;
+}
+
+void
+gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
+ unsigned long pfn)
+{
+ shared[ref].frame = pfn;
+ shared[ref].domid = domid;
+ wmb();
+ shared[ref].flags = GTF_accept_transfer;
+}
+
+unsigned long
+gnttab_end_foreign_transfer(grant_ref_t ref)
+{
+ unsigned long frame = 0;
+ uint16_t flags;
+
+ flags = shared[ref].flags;
+ ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed));
+
+ /*
+ * If a transfer is committed then wait for the frame address to appear.
+ * Otherwise invalidate the grant entry against future use.
+ */
+ if ( likely(flags != GTF_accept_transfer) ||
+ (cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
+ while ( unlikely((frame = shared[ref].frame) == 0) )
+ cpu_relax();
+
+ put_free_entry(ref);
+
+ return frame;
+}
+
+void
+gnttab_free_grant_references(uint16_t count, grant_ref_t head)
+{
+ /* TODO: O(N)...? */
+ grant_ref_t to_die = 0, next = head;
+ int i;
+
+ for ( i = 0; i < count; i++ )
+ to_die = next;
+ next = gnttab_free_list[next];
+ put_free_entry( to_die );
+}
+
+int
+gnttab_alloc_grant_references(uint16_t count, grant_ref_t *head,
+ grant_ref_t *terminal)
+{
+ int i;
+ grant_ref_t h = gnttab_free_head;
+
+ for ( i = 0; i < count; i++ )
+ if ( unlikely(get_free_entry() == -1) )
+ goto not_enough_refs;
+
+ *head = h;
+ *terminal = gnttab_free_head;
+
+ return 0;
+
+not_enough_refs:
+ gnttab_free_head = h;
+ return -ENOSPC;
+}
+
+int
+gnttab_claim_grant_reference(grant_ref_t *private_head, grant_ref_t terminal )
+{
+ grant_ref_t g;
+ if ( unlikely((g = *private_head) == terminal) )
+ return -ENOSPC;
+ *private_head = gnttab_free_list[g];
+ return g;
+}
+
+void
+gnttab_release_grant_reference( grant_ref_t *private_head,
+ grant_ref_t release )
+{
+ gnttab_free_list[release] = *private_head;
+ *private_head = release;
+}
+#ifdef notyet
+static int
+grant_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
+ int flag, struct thread *td)
+{
+
+ int ret;
+ privcmd_hypercall_t hypercall;
+
+ /* XXX Need safety checks here if using for anything other
+ * than debugging */
+ return -ENOSYS;
+
+ if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
+ return -ENOSYS;
+
+ if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
+ return -EFAULT;
+
+ if ( hypercall.op != __HYPERVISOR_grant_table_op )
+ return -ENOSYS;
+
+ /* hypercall-invoking asm taken from privcmd.c */
+ __asm__ __volatile__ (
+ "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
+ "movl 4(%%eax),%%ebx ;"
+ "movl 8(%%eax),%%ecx ;"
+ "movl 12(%%eax),%%edx ;"
+ "movl 16(%%eax),%%esi ;"
+ "movl 20(%%eax),%%edi ;"
+ "movl (%%eax),%%eax ;"
+ TRAP_INSTR "; "
+ "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
+ : "=a" (ret) : "0" (&hypercall) : "memory" );
+
+ return ret;
+
+}
+
+static struct cdevsw gnttab_cdevsw = {
+ d_ioctl: grant_ioctl,
+};
+
+static int
+grant_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len;
+ unsigned int i;
+ grant_entry_t *gt;
+
+ gt = (grant_entry_t *)shared;
+ len = 0;
+
+ for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
+ /* TODO: safety catch here until this can handle >PAGE_SIZE output */
+ if (len > (PAGE_SIZE - 200))
+ {
+ len += sprintf( page + len, "Truncated.\n");
+ break;
+ }
+
+ if ( gt[i].flags )
+ len += sprintf( page + len,
+ "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n",
+ i,
+ gt[i].flags,
+ gt[i].domid,
+ gt[i].frame );
+
+ *eof = 1;
+ return len;
+}
+
+static int
+grant_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ /* TODO: implement this */
+ return -ENOSYS;
+}
+#endif
+static int
+gnttab_init(void *unused)
+{
+ gnttab_setup_table_t setup;
+ unsigned long frames[NR_GRANT_FRAMES];
+ int i;
+
+ setup.dom = DOMID_SELF;
+ setup.nr_frames = NR_GRANT_FRAMES;
+ setup.frame_list = frames;
+
+ if (HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0)
+ panic("grant table setup failed\n");
+ if (setup.status != 0)
+ panic("non-zero status in grant table setup\n");
+ shared = (grant_entry_t *)kmem_alloc_nofault(kernel_map, NR_GRANT_FRAMES);
+
+ for (i = 0; i < NR_GRANT_FRAMES; i++)
+ pmap_kenter_ma((vm_offset_t)(shared + (i*PAGE_SIZE)), frames[i] << PAGE_SHIFT);
+
+ for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
+ gnttab_free_list[i] = i + 1;
+#if 0
+ /*
+ * /proc/xen/grant : used by libxc to access grant tables
+ */
+ if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
+ {
+ WPRINTK("Unable to create grant xen proc entry\n");
+ return -1;
+ }
+
+ grant_file_ops.read = grant_pde->proc_fops->read;
+ grant_file_ops.write = grant_pde->proc_fops->write;
+
+ grant_pde->proc_fops = &grant_file_ops;
+
+ grant_pde->read_proc = &grant_read;
+ grant_pde->write_proc = &grant_write;
+#endif
+ printk("Grant table initialized\n");
+ return 0;
+}
+
+SYSINIT(gnttab, SI_SUB_PSEUDO, SI_ORDER_FIRST, gnttab_init, NULL);
{
int i;
#ifdef WRITABLE_PAGETABLES
+ XENPRINTF("using writable pagetables\n");
HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
#endif
/* allocate remainder of NKPT pages */
for (i = 0; i < NKPT-1; i++, tmpindex++)
- PT_SET_VA(((unsigned long *)startinfo->pt_base) + KPTDI + i + 1, (tmpindex << PAGE_SHIFT)| PG_M | PG_RW | PG_V | PG_A, TRUE);
+ PD_SET_VA(((unsigned long *)startinfo->pt_base) + KPTDI + i + 1, (tmpindex << PAGE_SHIFT)| PG_M | PG_RW | PG_V | PG_A, TRUE);
tmpindex += NKPT-1;
PT_UPDATES_FLUSH();
* CMAP1/CMAP2 are used for zeroing and copying pages.
* CMAP3 is used for the idle process page zeroing.
*/
- SYSMAP(caddr_t, CMAP1, CADDR1, 1)
- SYSMAP(caddr_t, CMAP2, CADDR2, 1)
- SYSMAP(caddr_t, CMAP3, CADDR3, 1)
+ SYSMAP(caddr_t, CMAP1, CADDR1, 1);
+ SYSMAP(caddr_t, CMAP2, CADDR2, 1);
+ SYSMAP(caddr_t, CMAP3, CADDR3, 1);
+
PT_CLEAR_VA(CMAP3, TRUE);
mtx_init(&CMAPCADDR12_lock, "CMAPCADDR12", NULL, MTX_DEF);
PT_CLEAR_VA(CMAP2, FALSE);
for (i = 0; i < NKPT; i++)
- PT_CLEAR_VA(&PTD[i], FALSE);
+ PD_CLEAR_VA(&PTD[i], FALSE);
PT_UPDATES_FLUSH();
#ifdef XEN_UNNEEDED
/* Turn on PG_G on kernel page(s) */
pte_store(pte, pa | PG_RW | PG_V | pgeflag);
}
+/*
+ * Add a wired page to the kva.
+ * Note: not SMP coherent.
+ */
+PMAP_INLINE void
+pmap_kenter_ma(vm_offset_t va, vm_paddr_t ma)
+{
+ pt_entry_t *pte;
+
+ pte = vtopte(va);
+ PT_SET_VA_MA(pte, ma | PG_RW | PG_V | pgeflag, TRUE);
+}
+
/*
* Remove a page from the kernel pagetables.
* Note: not SMP coherent.
--- /dev/null
+/******************************************************************************
+ * gnttab.h
+ *
+ * Two sets of functionality:
+ * 1. Granting foreign access to our memory reservation.
+ * 2. Accessing others' memory reservations via grant references.
+ * (i.e., mechanisms for both sender and recipient of grant references)
+ *
+ * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2005, Christopher Clark
+ */
+
+#ifndef __ASM_GNTTAB_H__
+#define __ASM_GNTTAB_H__
+
+#include <machine/hypervisor.h>
+#include <machine/hypervisor-ifs.h>
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#define NR_GRANT_FRAMES 4
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+
+int
+gnttab_grant_foreign_access(
+ domid_t domid, unsigned long frame, int readonly);
+
+void
+gnttab_end_foreign_access(
+ grant_ref_t ref, int readonly);
+
+int
+gnttab_grant_foreign_transfer(
+ domid_t domid, unsigned long pfn);
+
+unsigned long
+gnttab_end_foreign_transfer(
+ grant_ref_t ref);
+
+int
+gnttab_query_foreign_access(
+ grant_ref_t ref );
+
+/*
+ * operations on reserved batches of grant references
+ */
+int
+gnttab_alloc_grant_references(
+ uint16_t count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal );
+
+void
+gnttab_free_grant_references(
+ uint16_t count, grant_ref_t private_head );
+
+int
+gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal
+);
+
+void
+gnttab_release_grant_reference(
+ grant_ref_t *private_head, grant_ref_t release );
+
+void
+gnttab_grant_foreign_access_ref(
+ grant_ref_t ref, domid_t domid, unsigned long frame, int readonly);
+
+void
+gnttab_grant_foreign_transfer_ref(
+ grant_ref_t, domid_t domid, unsigned long pfn);
+
+
+#endif /* __ASM_GNTTAB_H__ */
#define u32 uint32_t
#define u64 uint64_t
+#define CONFIG_XEN_BLKDEV_GRANT
#include <machine/xen-public/xen.h>
#include <machine/xen-public/io/domain_controller.h>
#include <machine/xen-public/io/netif.h>
#include <machine/xen-public/event_channel.h>
#include <machine/xen-public/sched_ctl.h>
#include <machine/xen-public/physdev.h>
+#include <machine/xen-public/grant_table.h>
#undef blkif_sector_t /* XXX pre-processor didn't do the */
#define blkif_sector_t uint64_t /* right thing */
* Assembler stubs for hyper-calls.
*/
-static inline int HYPERVISOR_set_trap_table(trap_info_t *table)
+static inline int
+HYPERVISOR_set_trap_table(trap_info_t *table)
{
int ret;
__asm__ __volatile__ (
-static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
+static inline int
+HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
+static inline int
+HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_set_callbacks(
+static inline int
+HYPERVISOR_set_callbacks(
unsigned long event_selector, unsigned long event_address,
unsigned long failsafe_selector, unsigned long failsafe_address)
{
return ret;
}
-static inline int HYPERVISOR_fpu_taskswitch(void)
+static inline int
+HYPERVISOR_fpu_taskswitch(void)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_yield(void)
+static inline int
+HYPERVISOR_yield(void)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_block(void)
+static inline int
+HYPERVISOR_block(void)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_shutdown(void)
+static inline int
+HYPERVISOR_shutdown(void)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_reboot(void)
+static inline int
+HYPERVISOR_reboot(void)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_suspend(unsigned long srec)
+static inline int
+HYPERVISOR_suspend(unsigned long srec)
{
int ret;
/* NB. On suspend, control software expects a suspend record in %esi. */
return ret;
}
-static inline long HYPERVISOR_set_timer_op(uint64_t timeout)
+static inline long
+HYPERVISOR_set_timer_op(uint64_t timeout)
{
int ret;
unsigned long timeout_hi = (unsigned long)(timeout>>32);
return ret;
}
-static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
+static inline int
+HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
{
int ret;
dom0_op->interface_version = DOM0_INTERFACE_VERSION;
return ret;
}
-static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value)
+static inline int
+HYPERVISOR_set_debugreg(int reg, unsigned long value)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline unsigned long HYPERVISOR_get_debugreg(int reg)
+static inline unsigned long
+HYPERVISOR_get_debugreg(int reg)
{
unsigned long ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_update_descriptor(
+static inline int
+HYPERVISOR_update_descriptor(
unsigned long pa, unsigned long word1, unsigned long word2)
{
int ret;
return ret;
}
-static inline int HYPERVISOR_set_fast_trap(int idx)
+static inline int
+HYPERVISOR_set_fast_trap(int idx)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_dom_mem_op(unsigned int op,
- unsigned long *pages,
- unsigned long nr_pages)
+static inline int
+HYPERVISOR_dom_mem_op(unsigned int op,
+ unsigned long *pages,
+ unsigned long nr_pages)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_multicall(void *call_list, int nr_calls)
+static inline int
+HYPERVISOR_multicall(void *call_list, int nr_calls)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_update_va_mapping(
+static inline int
+HYPERVISOR_update_va_mapping(
unsigned long page_nr, unsigned long new_val, unsigned long flags)
{
int ret;
return ret;
}
-static inline int HYPERVISOR_event_channel_op(void *op)
+static inline int
+HYPERVISOR_event_channel_op(void *op)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_xen_version(int cmd)
+static inline int
+HYPERVISOR_xen_version(int cmd)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static inline int HYPERVISOR_console_io(int cmd, int count, char *str)
+static inline int
+HYPERVISOR_console_io(int cmd, int count, char *str)
{
int ret;
__asm__ __volatile__ (
return ret;
}
-static __inline int HYPERVISOR_console_write(char *str, int count)
+static inline int
+HYPERVISOR_console_write(char *str, int count)
{
return HYPERVISOR_console_io(CONSOLEIO_write, count, str);
}
-static inline int HYPERVISOR_physdev_op(void *physdev_op)
+static inline int
+HYPERVISOR_physdev_op(void *physdev_op)
{
int ret;
+ unsigned long ign;
+
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_physdev_op),
- "b" (physdev_op) : "memory" );
+ : "=a" (ret), "=b" (ign)
+ : "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
+ : "memory" );
return ret;
}
-static inline int HYPERVISOR_update_va_mapping_otherdomain(
- unsigned long page_nr, pte_t new_val, unsigned long flags, domid_t domid)
+static inline int
+HYPERVISOR_grant_table_op(
+ unsigned int cmd, void *uop, unsigned int count)
{
int ret;
+ unsigned long ign1, ign2, ign3;
+
__asm__ __volatile__ (
TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
- "b" (page_nr), "c" ((new_val).pte_low), "d" (flags), "S" (domid) :
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
+ : "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_update_va_mapping_otherdomain(
+ unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
+{
+ int ret;
+ unsigned long ign1, ign2, ign3, ign4;
+
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
+ : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
+ "1" (va), "2" ((new_val).pte_low), "3" (flags), "4" (domid) :
"memory" );
-
+
return ret;
}
-static inline int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
+static inline int
+HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
{
int ret;
__asm__ __volatile__ (
#endif
#define ALWAYS_SYNC 0
+#define PT_DEBUG
+
+#ifdef PT_DEBUG
+#define PT_LOG() printk("WP PT_SET %s:%d\n", __FILE__, __LINE__)
+#else
+#define PT_LOG()
+#endif
+
#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
#define PT_GET(_ptp) \
#ifdef WRITABLE_PAGETABLES
#define PT_SET_VA(_ptp,_npte,sync) do { \
PMAP_REF((_ptp), xpmap_ptom(_npte)); \
- *(_ptp) = xpmap_ptom((_npte)); \
+ PT_LOG(); \
+ *(_ptp) = xpmap_ptom((_npte)); \
} while (/*CONSTCOND*/0)
-#define PT_SET_VA_MA(_ptp,_npte,sync) do { \
+#define PT_SET_VA_MA(_ptp,_npte,sync) do { \
PMAP_REF((_ptp), (_npte)); \
- *(_ptp) = (_npte); \
+ PT_LOG(); \
+ *(_ptp) = (_npte); \
} while (/*CONSTCOND*/0)
#define PT_CLEAR_VA(_ptp, sync) do { \
PMAP_REF((pt_entry_t *)(_ptp), 0); \
- *(_ptp) = 0; \
+ PT_LOG(); \
+ *(_ptp) = 0; \
} while (/*CONSTCOND*/0)
#define PD_SET_VA(_ptp,_npte,sync) do { \
xpmap_ptom((_npte))); \
if (sync || ALWAYS_SYNC) xen_flush_queue(); \
} while (/*CONSTCOND*/0)
-#define PD_SET_VA_MA(_ptp,_npte,sync) do { \
+#define PD_SET_VA_MA(_ptp,_npte,sync) do { \
PMAP_REF((_ptp), (_npte)); \
xen_queue_pt_update((pt_entry_t *)vtomach((_ptp)), (_npte)); \
if (sync || ALWAYS_SYNC) xen_flush_queue(); \
xpmap_ptom(_npte)); \
if (sync || ALWAYS_SYNC) xen_flush_queue(); \
} while (/*CONSTCOND*/0)
-#define PT_SET_VA_MA(_ptp,_npte,sync) do { \
+#define PT_SET_VA_MA(_ptp,_npte,sync) do { \
PMAP_REF((_ptp), (_npte)); \
- xen_queue_pt_update((pt_entry_t *)vtomach(_ptp), _npte); \
+ xen_queue_pt_update((pt_entry_t *)vtomach(_ptp), _npte);\
if (sync || ALWAYS_SYNC) xen_flush_queue(); \
} while (/*CONSTCOND*/0)
#define PT_CLEAR_VA(_ptp, sync) do { \
#include <machine/ctrl_if.h>
#include <machine/xenfunc.h>
+
+
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+#include <machine/gnttab.h>
+#endif
+
/* prototypes */
struct xb_softc;
static void xb_startio(struct xb_softc *sc);
static void xb_vbdinit(void);
static void blkif_control_send(blkif_request_t *req, blkif_response_t *rsp);
static void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
+static void blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp, unsigned long address);
struct xb_softc {
device_t xb_dev;
#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, PAGE_SIZE)
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+static domid_t rdomid = 0;
+static grant_ref_t gref_head, gref_terminal;
+#define MAXIMUM_OUTSTANDING_BLOCK_REQS \
+ (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
+#endif
+
+
static unsigned long rec_ring_free;
blkif_request_t rec_ring[BLK_RING_SIZE];
rec_ring_free = id;
}
-static inline void translate_req_to_pfn(blkif_request_t *xreq,
- blkif_request_t *req)
+static inline void
+translate_req_to_pfn(blkif_request_t *xreq,
+ blkif_request_t *req)
{
int i;
xreq->sector_number = req->sector_number;
for ( i = 0; i < req->nr_segments; i++ ){
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ xreq->frame_and_sects[i] = req->frame_and_sects[i];
+#else
xreq->frame_and_sects[i] = xpmap_mtop(req->frame_and_sects[i]);
+#endif
}
}
xreq->sector_number = req->sector_number;
for ( i = 0; i < req->nr_segments; i++ ){
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ xreq->frame_and_sects[i] = req->frame_and_sects[i];
+#else
xreq->frame_and_sects[i] = xpmap_ptom(req->frame_and_sects[i]);
+#endif
}
}
int s, queued = 0;
unsigned long id;
unsigned int fsect, lsect;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ int ref;
+#endif
if (unlikely(blkif_state != BLKIF_STATE_CONNECTED))
req->nr_segments = 1; /* not doing scatter/gather since buffer
* chaining is not supported.
*/
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ /* install a grant reference. */
+ ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+ KASSERT( ref != -ENOSPC, ("grant_reference failed") );
+
+ gnttab_grant_foreign_access_ref(
+ ref,
+ rdomid,
+ buffer_ma >> PAGE_SHIFT,
+ req->operation & 1 ); /* ??? */
+
+ req->frame_and_sects[0] =
+ (((uint32_t) ref) << 16) | (fsect << 3) | lsect;
+#else
/*
* upper bits represent the machine address of the buffer and the
* lower bits is the number of sectors to be read/written.
*/
req->frame_and_sects[0] = buffer_ma | (fsect << 3) | lsect;
-
+#endif
/* Keep a private copy so we can reissue requests when recovering. */
translate_req_to_pfn( &rec_ring[id], req);
memset(&req, 0, sizeof(req));
req.operation = BLKIF_OP_PROBE;
req.nr_segments = 1;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ blkif_control_probe_send(&req, &rsp,
+ (unsigned long)(vtomach(buf)));
+
+#else
req.frame_and_sects[0] = vtomach(buf) | 7;
blkif_control_send(&req, &rsp);
-
+#endif
if ( rsp.status <= 0 ) {
printk("xb_identify: Could not identify disks (%d)\n", rsp.status);
free(buf, M_DEVBUF);
/***************************** COMMON CODE *******************************/
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+static void
+blkif_control_probe_send(blkif_request_t *req, blkif_response_t *rsp,
+ unsigned long address)
+{
+ int ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+ KASSERT( ref != -ENOSPC, ("couldn't get grant reference") );
+
+ gnttab_grant_foreign_access_ref( ref, rdomid, address >> PAGE_SHIFT, 0 );
+
+ req->frame_and_sects[0] = (((uint32_t) ref) << 16) | 7;
+
+ blkif_control_send(req, rsp);
+}
+#endif
+
void
blkif_control_send(blkif_request_t *req, blkif_response_t *rsp)
{
blkif_evtchn = status->evtchn;
blkif_irq = bind_evtchn_to_irq(blkif_evtchn);
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ rdomid = status->domid;
+#endif
+
err = intr_add_handler("xbd", blkif_irq,
(driver_intr_t *)xb_response_intr, NULL,
printk("[XEN] Initialising virtual block device driver\n");
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ if ( 0 > gnttab_alloc_grant_references( MAXIMUM_OUTSTANDING_BLOCK_REQS,
+ &gref_head, &gref_terminal ))
+ return;
+ printk("Blkif frontend is using grant tables.\n");
+#endif
+
+
rec_ring_free = 0;
for (i = 0; i < BLK_RING_SIZE; i++) {
rec_ring[i].id = i+1;
}
#endif
-/* XXXXX THIS IS A TEMPORARY FUNCTION UNTIL WE GET GRANT TABLES */
-
void
blkif_completion(blkif_request_t *req)
{
int i;
+#ifdef CONFIG_XEN_BLKDEV_GRANT
+ grant_ref_t gref;
+
+ for ( i = 0; i < req->nr_segments; i++ )
+ {
+ gref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ gnttab_release_grant_reference(&gref_head, gref);
+ }
+#else
+ /* This is a hack to get the dirty logging bits set */
switch ( req->operation )
{
case BLKIF_OP_READ:
}
break;
}
-
+#endif
}
MTX_SYSINIT(ioreq, &blkif_io_lock, "BIO LOCK", MTX_SPIN | MTX_NOWITNESS); /* XXX how does one enroll a lock? */
SYSINIT(xbdev, SI_SUB_PSEUDO, SI_ORDER_ANY, xb_init, NULL)